package com.example.java2024_5_1searcher.searcher;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.core.type.TypeReference;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;

import java.io.File;
import java.io.IOException;
import java.util.*;

//构建正排索引，倒排索引
public class Index {
    //正排索引
   ArrayList<DocInfo> forwardIndex = new ArrayList<DocInfo>();
    //倒排索引
    private HashMap<String, ArrayList<Weight>> invertedIndex = new HashMap<>();
    private ObjectMapper objectMapper = new ObjectMapper();

    static String INDEX_PATH =null;
    static {
        if(Flag.flag){
           INDEX_PATH = "E:\\java_jdk\\jdk-8u411-docs-all\\docs\\api";
        }else {
            INDEX_PATH ="/root/do_searcher/api";
        }

    }
    private Object locker1=new Object();
    private Object locker2=new Object();

    public DocInfo forwardIndex(int index) {
        return forwardIndex.get(index);
    }

    public ArrayList<Weight> invertedIndex(String key) {
        return invertedIndex.get(key);
    }

    public void addDoc(String title, String text, String url) {
        DocInfo docInfo = structure_forwardIndex(title, text, url);
        structure_invertedIndex(docInfo);
    }

    public DocInfo structure_forwardIndex(String title, String text, String url) {
        synchronized (locker1) {
            DocInfo docInfo = new DocInfo(forwardIndex.size(), title, text, url);
            forwardIndex.add(docInfo);
            return docInfo;
        }
    }

    public void structure_invertedIndex(DocInfo docInfo) {
        //用来存储正文，标题出现次数
        HashMap<String, WordCnt> hashMap = new HashMap<>();
        //遍历得到每个词在标题出现次数
        List<Term> terms1 = ToAnalysis.parse(docInfo.getTitle()).getTerms();
        for (Term term : terms1) {
            String str = term.getName();
            WordCnt wordCnt = hashMap.get(str);
            if (wordCnt == null) {
                WordCnt wordCnt1=new WordCnt(1,0);
                hashMap.put(str, wordCnt1);
            } else {
                wordCnt.titleCount+=1;
            }
        }
        //遍历得到每个词在正文出现次数
        List<Term> terms2 = ToAnalysis.parse(docInfo.getText()).getTerms();
        for (Term term : terms2) {
            String str = term.getName();
            WordCnt wordCnt = hashMap.get(str);
            if (wordCnt == null) {
                WordCnt wordCnt1=new WordCnt(0,1);
                hashMap.put(str, wordCnt1);
            } else {
                wordCnt.contentCount+=1;
            }
        }
        //将hashmap存储的信息进行合并
        Iterator<Map.Entry<String, WordCnt>> iterator = hashMap.entrySet().iterator();
        while (iterator.hasNext()) {
            synchronized (locker2) {
                Map.Entry<String, WordCnt> entry = iterator.next();
                String key = entry.getKey();
                WordCnt value = entry.getValue();
                ArrayList<Weight> arrayList = invertedIndex.get(key);
                if (arrayList == null) {
                    Weight weight = new Weight(docInfo.id, value.getTitleCount() * 10 + value.getContentCount());
                    ArrayList<Weight> arrayList1 = new ArrayList<>();
                    arrayList1.add(weight);
                    invertedIndex.put(key, arrayList1);
                } else {
                    Weight weight = new Weight(docInfo.id, value.getTitleCount() * 10 + value.getContentCount());
                    arrayList.add(weight);
                }
            }
        }
    }
    //将正排，倒排索引加载到磁盘上
    public void save(){
        // 使用两个文件, 分别保存正排和倒排
        long beg = System.currentTimeMillis();
        System.out.println("保存索引开始!");
        // 1. 先判定一下索引对应的目录是否存在, 不存在就创建.
        File indexPathFile = new File(INDEX_PATH);
        if (!indexPathFile.exists()) {
            indexPathFile.mkdirs();
        }
        File forwardIndexFile = new File(INDEX_PATH + "forward.txt");
        File invertedIndexFile = new File(INDEX_PATH + "inverted.txt");
        try {
            objectMapper.writeValue(forwardIndexFile, forwardIndex);
            objectMapper.writeValue(invertedIndexFile, invertedIndex);
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("保存索引完成! 消耗时间: " + (end - beg) + " ms");
    }
    //将正排、倒排索引从磁盘上加载到内存上
    public void load(){
        long beg = System.currentTimeMillis();
        System.out.println("加载索引开始!");
        // 1. 先设置一下加载索引的路径
        File forwardIndexFile = new File(INDEX_PATH + "forward.txt");
        File invertedIndexFile = new File(INDEX_PATH + "inverted.txt");
        try {
            forwardIndex = objectMapper.readValue(forwardIndexFile, new TypeReference<ArrayList<DocInfo>>() {});
            invertedIndex = objectMapper.readValue(invertedIndexFile, new TypeReference<HashMap<String, ArrayList<Weight>>>() {});
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("加载索引结束! 消耗时间: " + (end - beg) + " ms");
    }

    public static void main(String[] args) {
        Index index = new Index();
        index.load();
        for(DocInfo docInfo:index.forwardIndex){
            System.out.println(docInfo.toString());
        }
        System.out.println("索引加载完成");
    }

}
